package com.luoyx.vjsb.admin.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.luoyx.vjsb.common.query.CommonQuery;
import com.luoyx.vjsb.common.util.AjaxResult;
import com.luoyx.vjsb.redis.RedisTemplateHelper;
import com.luoyx.vjsb.redis.vo.RedisInfo;
import com.luoyx.vjsb.redis.vo.RedisVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *
 * </p>
 *
 * @author luoyuanxiang
 * @date 2020/5/5 10:41
 */
@RestController
@Api(tags = "Redis缓存管理接口")
@RequestMapping("/api/redis")
@PreAuthorize("hasRole('ROLE_supper_admin')")
public class RedisController {

    /**
     * 最大获取10万个键值
     */
    private static final int maxSize = 100000;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private RedisTemplateHelper redisTemplateHelper;

    @GetMapping("getAll")
    @ApiOperation(value = "分页获取全部")
    public AjaxResult<List<RedisVo>> getAllByPage(@RequestParam(required = false) String key,
                                                  CommonQuery pageVo) {
        List<RedisVo> list = new ArrayList<>();

        if (StrUtil.isNotBlank(key)) {
            key = "*" + key + "*";
        } else {
            key = "*";
        }
        Set<String> keys = redisTemplateHelper.keys(key);
        int size = keys.size();
        // 限制10万个
        if (size > maxSize) {
            size = maxSize;
        }
        int i = 0;
        for (String s : keys) {
            if (i > size) {
                break;
            }
            RedisVo redisVo = new RedisVo(s, stringRedisTemplate.opsForValue().get(s), stringRedisTemplate.getExpire(s, TimeUnit.MINUTES));
            list.add(redisVo);
            i++;
        }
        return AjaxResult.success(list);
    }

    @GetMapping(value = "/getByKey/{key}")
    @ApiOperation(value = "通过key获取")
    public AjaxResult<Map<String, Object>> getByKey(@PathVariable String key) {

        Map<String, Object> map = new HashMap<>();
        String value = stringRedisTemplate.opsForValue().get(key);
        Long expireTime = stringRedisTemplate.getExpire(key, TimeUnit.SECONDS);
        map.put("value", value);
        map.put("expireTime", expireTime);
        return AjaxResult.success(map);
    }

    @PostMapping(value = "/save")
    @ApiOperation(value = "添加或编辑")
    public AjaxResult<String> save(@RequestParam String key,
                               @RequestParam String value,
                               @RequestParam Long expireTime) {

        if (expireTime < 0) {
            stringRedisTemplate.opsForValue().set(key, value);
        } else if (expireTime > 0) {
            stringRedisTemplate.opsForValue().set(key, value, expireTime, TimeUnit.SECONDS);
        }
        return AjaxResult.success("保存成功");
    }

    @PostMapping(value = "/delByKeys")
    @ApiOperation(value = "批量删除")
    public AjaxResult<String> delByKeys(@RequestParam String[] ids) {

        for (String key : ids) {
            stringRedisTemplate.delete(key);
        }
        return AjaxResult.success("删除成功");
    }

    @PostMapping(value = "/delAll")
    @ApiOperation(value = "全部删除")
    public AjaxResult<String> delAll() {
        stringRedisTemplate.delete(redisTemplateHelper.keys("*"));
        return AjaxResult.success("删除成功");
    }

    @GetMapping(value = "/getKeySize")
    @ApiOperation(value = "获取实时key大小")
    public AjaxResult<Map<String, Object>> getKeySize() {

        Map<String, Object> map = new HashMap<>(16);
        map.put("keySize", Objects.requireNonNull(stringRedisTemplate.getConnectionFactory()).getConnection().dbSize());
        map.put("time", DateUtil.format(new Date(), "HH:mm:ss"));
        return AjaxResult.success(map);
    }

    @GetMapping(value = "/getMemory")
    @ApiOperation(value = "获取实时内存大小")
    public AjaxResult<Map<String, Object>> getMemory() {

        Map<String, Object> map = new HashMap<>(16);
        Properties memory = Objects.requireNonNull(stringRedisTemplate.getConnectionFactory()).getConnection().info("memory");
        assert memory != null;
        map.put("memory", memory.get("used_memory"));
        map.put("time", DateUtil.format(new Date(), "HH:mm:ss"));
        return AjaxResult.success(map);
    }

    @GetMapping(value = "/info")
    @ApiOperation(value = "获取Redis信息")
    public AjaxResult<List<RedisInfo>> info() {

        List<RedisInfo> infoList = new ArrayList<>();
        Properties properties = Objects.requireNonNull(stringRedisTemplate.getConnectionFactory()).getConnection().info();
        assert properties != null;
        Set<Object> keys = properties.keySet();
        for (Object key : keys) {
            String value = properties.get(key).toString();
            RedisInfo redisInfo = new RedisInfo();
            redisInfo.setKey(key.toString());
            redisInfo.setValue(value);
            infoList.add(redisInfo);
        }
        return AjaxResult.success(infoList);
    }
}
